package com.yeyks.commonReference.service.activity.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.yeyks.activity.dal.domain.ActivityList;
import com.yeyks.activity.dal.domain.ActivityPrizeInfo;
import com.yeyks.activity.dal.domain.ActivityPrizeList;
import com.yeyks.activity.dto.ActivityListDTO;
import com.yeyks.activity.param.ActivityPrizeOneAddParam;
import com.yeyks.activity.param.ActivityPrizeOneUpdateParam;
import com.yeyks.activity.param.ActivityPrizeTwoAddParam;
import com.yeyks.activity.param.ActivityPrizeTwoUpdateParam;
import com.yeyks.activity.service.ActivityListService;
import com.yeyks.activity.service.ActivityPrizeInfoService;
import com.yeyks.activity.service.ActivityPrizeListService;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.base.PageResult;
import com.yeyks.common.constants.activity.ActivityPrizeInfoTypeConstant;
import com.yeyks.common.param.PageParam;
import com.yeyks.common.utils.RedisUtil;
import com.yeyks.commonReference.service.activity.ActivityWebBaseService;
import com.yeyks.commonReference.service.other.CouponInfoService;
import com.yeyks.other.dal.domain.CouponInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author shuai
 * @date 2019/11/28 10:22
 */
@Service
@Slf4j
public class ActivityWebBaseServiceImpl implements ActivityWebBaseService {

    @Autowired
    private ActivityListService activityListService;
    @Autowired
    private ActivityPrizeInfoService activityPrizeInfoService;
    @Autowired
    private ActivityPrizeListService activityPrizeListService;
    @Autowired
    private CouponInfoService couponInfoService;
    @Autowired
    private RedisUtil redisUtil;
    private static final String key = "redisLock:ActivityWebBaseServiceImpl:twoPrizeUpdate";

    /**
     * 活动列表
     *
     * @return
     */
    @Override
    public PageResult<ActivityList> getActivityList(PageParam page) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize());
        List<ActivityList> list = activityListService.list(new QueryWrapper<ActivityList>().orderByDesc(ActivityList.CREATE_TIME));
        return PageResult.getPageResult(list);
    }

    /**
     * 添加一级奖品
     *
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer onePrizeAdd(ActivityPrizeOneAddParam param) {
        if (!ActivityPrizeInfoTypeConstant.COUPON.equals(param.getPrizeType())
                && 0 == param.getWhetherAppend()) {
            Arguments.intIsNull(param.getPubCount(), "发行量不能为空");
            Arguments.intIsNull(param.getPrizePrice(), "奖品金额不能为空");
        }
        Date date = new Date();
        ActivityPrizeInfo info = BeanUtil.toBean(param, ActivityPrizeInfo.class);
        if (ObjectUtil.isNotNull(param.getEndTime())) {
            info.setEndTime(new Date(param.getEndTime()));
        }
        info.setActivityCode(param.getActivityCode());
        info.setStatus(1);
        info.setGmtCreate(date);
        info.setPubCount(null == info.getPubCount() ? 0 : info.getPubCount());
        info.setRemainCount(null == info.getPubCount() ? 0 : info.getPubCount());
        info.setTakeCount(0);
        info.setLevel(1);
        if (ActivityPrizeInfoTypeConstant.COUPON.equals(param.getPrizeType())) {
            info.setWhetherAppend(1);
            info.setPrizePrice(null);
            info.setPubCount(null);
            info.setRemainCount(null);
            info.setTakeCount(null);
        }
        boolean save = activityPrizeInfoService.save(info);
        Arguments.isFalse(save, "添加一级奖品失败");
//        //如果没有下级需要写入奖品详情表中
//        if (0 == info.getWhetherAppend()) {
//            Arguments.isFalse(saveActivityPrizeList(info, param.getPubCount()), "添加一级奖品详情失败");
//        }
        return info.getId();
    }

//    /**
//     * 奖品详情表保存
//     *
//     * @param info
//     * @return
//     */
//    private Boolean saveActivityPrizeList(ActivityPrizeInfo info, Integer pubCount) {
//        if (ActivityPrizeInfoTypeConstant.COUPON.equals(info.getPrizeType())) {
//            return true;
//        }
//        List<ActivityPrizeList> lists = Lists.newArrayList();
//        if (null != pubCount && pubCount > 0) {
//            for (int i = 0; i < pubCount; i++) {
//                ActivityPrizeList list = new ActivityPrizeList();
//                list.setActivityCode(info.getActivityCode());
//                list.setPrizeId(info.getId());
//                list.setStatus(0);
//                list.setCreateTime(info.getGmtCreate());
//                lists.add(list);
//            }
//            return activityPrizeListService.insertByBatch(lists);
//        }
//        return true;
//    }

    /**
     * 添加二级奖品
     *
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean twoPrizeAdd(ActivityPrizeTwoAddParam param) {
        Date date = new Date();
        ActivityPrizeInfo info = activityPrizeInfoService.getById(param.getOnePrizeId());
        Arguments.beanIsNull(info, "该一级奖品不存在");
        Arguments.isTrue(info.getWhetherAppend() == 0, "该一级奖品不存在二级奖品");
        if (!ActivityPrizeInfoTypeConstant.COUPON.equals(info.getPrizeType())) {
            Arguments.intIsNull(param.getPubCount(), "非优惠券类型发行量必传");
        }
        ActivityPrizeInfo twoInfo = BeanUtil.toBean(param, ActivityPrizeInfo.class);
        twoInfo.setActivityCode(info.getActivityCode());
        twoInfo.setLevel(2);
        twoInfo.setWhetherAppend(0);
        twoInfo.setParentId(info.getId());
        twoInfo.setPrizeName(info.getPrizeName());
        twoInfo.setPrizeImageUrl(param.getPrizeImageUrl());
        twoInfo.setPrizeImageReturnUrl(param.getPrizeImageReturnUrl());
        twoInfo.setPrizeType(info.getPrizeType());
        twoInfo.setStatus(1);
        twoInfo.setPubCount(param.getPubCount());
        twoInfo.setTakeCount(0);
        twoInfo.setRemainCount(param.getPubCount());
        twoInfo.setRemark(info.getRemark());
        if (ObjectUtil.isNotNull(param.getEndTime())) {
            twoInfo.setEndTime(new Date(param.getEndTime()));
        }
        twoInfo.setPrizePrice(param.getPrizePrice());
        twoInfo.setChancePercent(param.getChancePercent());
        twoInfo.setGmtCreate(date);
        if (ActivityPrizeInfoTypeConstant.COUPON.equals(info.getPrizeType())) {
            Arguments.intIsNull(param.getCouponId(), "优惠券id不能为空");
            CouponInfo byId = couponInfoService.getById(param.getCouponId());
            Arguments.beanIsNull(byId, "该优惠券不存在");
            twoInfo.setPubCount(null);
            twoInfo.setRemainCount(null);
            twoInfo.setTakeCount(null);
            twoInfo.setCouponId(byId.getId());
            twoInfo.setCouponValue(String.valueOf(byId.getValidFee()));
            twoInfo.setPrizePrice(byId.getPrice());
        }
        boolean save = activityPrizeInfoService.save(twoInfo);
        Arguments.isFalse(save, "添加二级奖品失败");
//        //如果没有下级需要写入奖品详情表中
//        Arguments.isFalse(saveActivityPrizeList(twoInfo, param.getPubCount()), "添加奖品详情失败");
        return true;
    }

    /**
     * 修改一级奖品
     *
     * @param param
     * @return
     */
    @Override
    public Boolean onePrizeUpdate(ActivityPrizeOneUpdateParam param) {
        ActivityPrizeInfo byId = activityPrizeInfoService.getById(param.getId());
        Arguments.beanIsNull(byId, "该一级奖品不存在");
        Arguments.isTrue(2 == byId.getLevel(), "非一级奖品不能修改");
        byId.setOperatorId(param.getOperatorId());
        if (StrUtil.isNotBlank(param.getPrizeName())) {
            byId.setPrizeName(param.getPrizeName());
        }
        if (StrUtil.isNotBlank(param.getPrizeImageUrl())) {
            byId.setPrizeImageUrl(param.getPrizeImageUrl());
        }
        if (StrUtil.isNotBlank(param.getPrizeImageReturnUrl())) {
            byId.setPrizeImageReturnUrl(param.getPrizeImageReturnUrl());
        }
        if (ObjectUtil.isNotNull(param.getEndTime())) {
            byId.setEndTime(new Date(param.getEndTime()));
        }
        if (ObjectUtil.isNotNull(param.getPrizePrice())) {
            //优惠券类型一级奖品金额不能修改
            if (!ActivityPrizeInfoTypeConstant.COUPON.equals(byId.getPrizeType())) {
                byId.setPrizePrice(param.getPrizePrice());
            }
        }
        if (ObjectUtil.isNotNull(param.getChancePercent())) {
            byId.setChancePercent(param.getChancePercent());
        }
        //发行量修改
        updatePubCount(param.getPubCount(), byId);
        Arguments.isFalse(activityPrizeInfoService.updateById(byId), "修改一级奖品失败");
        return true;
    }

    /**
     * 修改券的发行量
     *
     * @param nowPubCount 将要修改的发行量值
     * @param byId
     */
    public void updatePubCount(Integer nowPubCount, ActivityPrizeInfo byId) {
        if (ObjectUtil.isNotNull(nowPubCount)) {
            if (!ActivityPrizeInfoTypeConstant.COUPON.equals(byId.getPrizeType())) {
                //数据库中的发行量
                Integer pubCount = byId.getPubCount();
                if (null == pubCount) {
                    byId.setPubCount(nowPubCount);
                    byId.setRemainCount(nowPubCount);
                    byId.setTakeCount(0);
                } else {
                    //如果修改的值比数据库中的值大
                    if (nowPubCount > pubCount) {
                        int count = nowPubCount - pubCount;
                        byId.setRemainCount(byId.getRemainCount() + count);
                        byId.setPubCount(nowPubCount);
                    } else {
                        int count = pubCount - nowPubCount;
                        byId.setRemainCount(byId.getRemainCount() - count);
                        byId.setPubCount(byId.getPubCount() - count);
                    }
                }
            }
        }
    }

    /**
     * 删除一级奖品
     *
     * @param prizeId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean onePrizeDel(Integer prizeId) {
        Arguments.intIsNull(prizeId, "一级奖品id不能为空");
        ActivityPrizeInfo byId = activityPrizeInfoService.getById(prizeId);
        Arguments.beanIsNull(byId, "该一级奖品不存在");
        Arguments.isTrue(2 == byId.getLevel(), "该一级奖品不存在");
        //查询该一级奖品是否有二级奖品
        List<ActivityPrizeInfo> list = activityPrizeInfoService.list(new QueryWrapper<ActivityPrizeInfo>()
                .eq(ActivityPrizeInfo.LEVEL, 2).eq(ActivityPrizeInfo.PARENT_ID, byId.getId()));
        //有二级奖品，则先删除二级奖品的奖品详情，再删除二级奖品
        if (CollectionUtil.isNotEmpty(list)) {
            //二级奖品id
            List<Integer> twoPrizeIds = Lists.transform(list, ActivityPrizeInfo::getId);
//            for (Integer twoPrizeId : twoPrizeIds) {
//                //删除奖品详情
//                deleteById(twoPrizeId);
//            }
            //删除二级奖品
            activityPrizeInfoService.removeByIds(twoPrizeIds);
        } else {
            // 没有二级奖品则先删除一级奖品的奖品列表
//            deleteById(byId.getId());
        }
        //删除一级奖品
        Arguments.isFalse(activityPrizeInfoService.removeById(byId.getId()), "删除失败");
        return true;
    }

    /**
     * 删除二级奖品
     *
     * @param prizeId
     * @return
     */
    @Override
    public Boolean twoPrizeDel(Integer prizeId) {
        Arguments.intIsNull(prizeId, "二级奖品id不能为空");
        ActivityPrizeInfo byId = activityPrizeInfoService.getById(prizeId);
        Arguments.beanIsNull(byId, "该二级奖品不存在");
        Arguments.isTrue(1 == byId.getLevel(), "该二级奖品不存在");
        //删除奖品详情
//        deleteById(byId.getId());
        //删除二级奖品
        Arguments.isFalse(activityPrizeInfoService.removeById(byId.getId()), "删除失败");
        return null;
    }

//    /**
//     * 通过奖品id删除奖品详情
//     *
//     * @param prizeId 奖品id
//     */
//    public void deleteById(Integer prizeId) {
//        //查询奖品详情
//        List<ActivityPrizeList> prizeLists = activityPrizeListService.list(new QueryWrapper<ActivityPrizeList>().eq(ActivityPrizeList.PRIZE_ID, prizeId));
//        //删除奖品详情
//        if (CollectionUtil.isNotEmpty(prizeLists)) {
//            List<Integer> idLists = Lists.transform(prizeLists, ActivityPrizeList::getId);
//            activityPrizeListService.removeByIds(idLists);
//        }
//    }

    /**
     * 修改二级奖品
     *
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean twoPrizeUpdate(ActivityPrizeTwoUpdateParam param) {
        redisUtil.runWithLock(key, () -> {
            ActivityPrizeInfo byId = activityPrizeInfoService.getById(param.getId());
            Arguments.beanIsNull(byId, "该二级奖品不存在");
            Arguments.isTrue(1 == byId.getLevel(), "非二级奖品不能修改");
            byId.setOperatorId(param.getOperatorId());
            //结束时间
            if (ObjectUtil.isNotNull(param.getEndTime())) {
                byId.setEndTime(new Date(param.getEndTime()));
            }
            //概率
            if (ObjectUtil.isNotNull(param.getChancePercent())
                    && null != byId.getChancePercent()
                    && !byId.getChancePercent().equals(param.getChancePercent())) {
                byId.setChancePercent(param.getChancePercent());
            }
            //奖品图片地址
            if (StrUtil.isNotEmpty(param.getPrizeImageUrl())) {
                byId.setPrizeImageUrl(param.getPrizeImageUrl());
            }
            //奖品中奖返回图片地址
            if (StrUtil.isNotEmpty(param.getPrizeImageReturnUrl())) {
                byId.setPrizeImageReturnUrl(param.getPrizeImageReturnUrl());
            }
            //奖品金额
            if (ObjectUtil.isNotNull(param.getPrizePrice())
                    && null != byId.getPrizePrice()
                    && !byId.getPrizePrice().equals(param.getPrizePrice())) {
                if (!ActivityPrizeInfoTypeConstant.COUPON.equals(byId.getPrizeType())) {
                    byId.setPrizePrice(param.getPrizePrice());
                }
            }
            if (ObjectUtil.isNotNull(param.getCouponId())
                    && null != byId.getPrizeType()
                    && ActivityPrizeInfoTypeConstant.COUPON.equals(byId.getPrizeType())) {
                CouponInfo couponInfo = couponInfoService.getById(param.getCouponId());
                Arguments.beanIsNull(byId, "该优惠券不存在");
                byId.setCouponId(couponInfo.getId());
                byId.setCouponValue(String.valueOf(couponInfo.getValidFee()));
                byId.setTakeCount(couponInfo.getGetCount());
                byId.setRemainCount(couponInfo.getRemainCount());
                byId.setPubCount(couponInfo.getCount());
                byId.setPrizePrice(couponInfo.getPrice());
            }
            //发行量修改
            updatePubCount(param.getPubCount(), byId);
            Arguments.isFalse(activityPrizeInfoService.updateById(byId), "修改二级奖品失败");
            return true;
        });
        return true;
    }

    /**
     * 双旦券列表
     *
     * @param type 券类型
     * @return
     */
    @Override
    public List<CouponInfo> couponList(Integer type) {
        List<CouponInfo> list = couponInfoService.list(new QueryWrapper<CouponInfo>()
                .eq(CouponInfo.TYPE, type)
                .eq(CouponInfo.STATUS, 2)
                .gt(CouponInfo.REMAIN_COUNT, 0));
        return null == list ? Lists.newArrayList() : list;
    }

    /**
     * 活动详情
     *
     * @param id 活动id
     * @return
     */
    @Override
    public ActivityListDTO detail(Integer id) {
        Arguments.intIsNull(id, "活动id不能为空");
        ActivityList activityList = activityListService.getById(id);
        Arguments.beanIsNull(activityList, "该活动不存在");
        ActivityListDTO activityListDTO = BeanUtil.toBean(activityList, ActivityListDTO.class);
        List<ActivityPrizeInfo> list = activityPrizeInfoService.list(new QueryWrapper<ActivityPrizeInfo>()
                .eq(ActivityPrizeInfo.ACTIVITY_CODE, activityList.getActivityCode())
                .eq(ActivityPrizeInfo.LEVEL, 1));
        activityListDTO.setActivityPrizeInfos(list);
        return activityListDTO;
    }

}
